from django.shortcuts import render

# Create your views here.
# OpenID 与用户信息进行一一绑定的相关逻辑
# QQ 登录整体流程：生成用户绑定链接 -------> 获取 code -------> 获取 token -------> 获取 openid -------> 保存 openid


# 生成用户绑定链接的逻辑段
# 前端行为说明：当用户点击 QQ 登录图标的时候，前端需发送一个 axios（Ajax）请求到当前后端接口
# 后端处理步骤：
# - 接收请求：处理前端发起的“获取 QQ 登录链接”请求
# - 业务逻辑：调用 QQLoginTool 工具类，生成 QQ 登录的跳转链接
# - 构造响应：返回包含状态码（code: 0 代表成功）和 QQ 登录链接（qq_login_url）的字典，供前端跳转使用
#步骤：
# - 1.生成QQLoginTool实例对象
# - 2.调用QQLoginTool实例对象的get_login_url方法，生成QQ登录的跳转链接
# - 3.返回响应
# 代码实现：
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.http import JsonResponse
from meiduo_mall import settings
import logging
logger = logging.getLogger('django')  # 日志对象，用于记录调试信息

class QQLoginURLView(View):

    def get(self,request):
        """获取QQ登录的url"""
        # 1.生成QQLoginTool实例对象
        # client_id:应用的APPID
        # client_secret:应用的APPKEY  appsecret
        # redirect_uri:回调地址，必须和QQ登录工具中设置的回调地址一致 (前端页面地址)
        qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID, 
                     client_secret=settings.QQ_CLIENT_SECRET, 
                     redirect_uri=settings.QQ_REDIRECT_URI,
                     state='xxxx')  # state：用于防止CSRF攻击（跨站请求伪造攻击）
        # 2.调用QQLoginTool实例对象的get_login_url方法，生成QQ登录的跳转链接
        qq_login_url = qq.get_qq_url()
        # 3.返回响应
        return JsonResponse({'code':0,'errmsg':'OK','login_url':qq_login_url})

# 需求：获取code，通过code换取token，再通过token换取openid

# 前端：
# 应该获取 用户同意登录的code。把这个code发送给后端

# 后端：
# 请求          获取code
# 业务逻辑      通过code换取token，再通过token换取openid
#               根据openid进行判断
#               如果没有绑定过，则需要绑定
#               如果绑定过，则直接登录

# 响应
# 路由          GET    oauth_callback/?code=xxxxxx

# 步骤
# 1. 获取code
# 2. 通过code换取token
# 3. 再通过token换取openid
# 4. 根据openid进行判断
# 5. 如果没有绑定过，则需要绑定
# 6. 如果绑定过，则直接登录
from apps.oauth.models import OAuthQQUser
from django.contrib.auth import login  # 用于状态保持
import json
from  apps.users.models import User
# OAuthQQView：处理QQ登录回调请求
class OauthQQView(View):

    def get(self,request):
        # 1. 获取code
        code = request.GET.get('code')
        if code is None:
            return JsonResponse({'code':400,'errmsg':'缺少code'})
        # 2. 通过code换取token
        qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID, 
                     client_secret=settings.QQ_CLIENT_SECRET, 
                     redirect_uri=settings.QQ_REDIRECT_URI,
                     state='xxxx')  # state：用于防止CSRF攻击（跨站请求伪造攻击）
        try:
            token = qq.get_access_token(code)
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code':400,'errmsg':'获取token失败'})
        # 3. 再通过token换取openid
        openid = qq.get_open_id(token)
        # 4. 根据openid进行判断
        try:
            # 如果openid绑定过，则直接登录
            qquser = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            from apps.oauth.utils import generic_openid
            access_token = generic_openid(openid)
            response = JsonResponse({'code':0,'errmsg':'OK','access_token':access_token})
            return response
        else:
            # 6. 如果绑定过，则直接登录
            
            # 设置session
            login(request,qquser.user)
            # 设置cookie
            response = JsonResponse({'code':0,'errmsg':'OK'})
            response.set_cookie('username',qquser.user.username)
            return response

    def post(self,request):
        data = json.loads(request.body.decode())
        mobile = data.get('mobile')
        password = data.get('password')
        sms_code = data.get('sms_code')
        # open_id = data.get('open_id')
        access_token = data.get('access_token')
        from apps.oauth.utils import check_access_token
        open_id = check_access_token(access_token)
        if open_id is None:
            return JsonResponse({'code':400,'errmsg':'access_token无效'})

        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 用户不存在，创建新用户
            # username=mobile意识着用户名和手机号一致
            user = User.objects.create_user(username=mobile,password=password,mobile=mobile)
        else:
            # 用户存在，验证密码
            if not user.check_password(password):
                return JsonResponse({'code':400,'errmsg':'用户名或密码错误'})
        # 用户与openid进行绑定
        OAuthQQUser.objects.create(user=user,openid=open_id)
        # 状态保持
        login(request,user)
        # 返回响应
        response = JsonResponse({'code':0,'errmsg':'OK'})
        response.set_cookie('username',user.username)
        return response
# 前端逻辑：
# 当用户输入手机号、密码、短信验证码后，发送axios请求到后端；请求需携带参数：mobile（手机号）、password（密码）、sms_code（短信验证码）、access_token（即openid）

# 后端逻辑：
# 请求处理：接收请求，获取请求携带的参数
# 业务逻辑：执行“用户与openid绑定”操作，并完成用户状态保持（登录态维持）
# 响应结果：返回code=0的成功标识，同时跳转到首页
# 路由配置：采用POST请求方式，路由为 oauth_callback/

# 具体步骤：
# 1. 接收前端发送的请求
# 2. 从请求中获取参数openid（通过access_token传递）
# 3. 根据请求中的手机号，查询对应的用户信息
# 4. 若手机号已注册：直接将该用户与openid进行绑定（完成状态保持）
# 5. 若手机号未注册：先创建新的User信息，再将新用户与openid进行绑定
# 6. 完成用户状态保持（如生成登录态标识：session/token等）
# 7. 向前端返回响应（提示成功并跳转首页）
# from itsdangerous import URLSafeTimedSerializer as Serializer
# from itsdangerous import BadData
# from django.conf import settings
# # 使用URLSafeTimedSerializer替代旧版本的Serializer
# s = Serializer(settings.SECRET_KEY, salt='oauth')
# # 创建token，有效期300秒
# token = s.dumps({'mobile':'18761233821'})
# # 解析token
# s.loads(token)
